package org.lane.riccochet.ui.screenmanager;

import java.awt.*;
import java.awt.image.*;
import java.lang.reflect.*;
import javax.swing.*;

public class ScreenManager {
	
	private GraphicsDevice device;
	
	public ScreenManager() {
		GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment();
		device = environment.getDefaultScreenDevice();
	}
	
	public DisplayMode[] getCompatibleDisplayModes() {
		return device.getDisplayModes();
	}
	
	public DisplayMode findFirstCompatibleMode(DisplayMode modes[]) {
		DisplayMode retVal = null;		
		DisplayMode goodModes[] = device.getDisplayModes();
		
		for(int i = 0; i < modes.length; ++i) {
			for(int j = 0; j < goodModes.length; ++j) {
				if(displayModesMatch(modes[i], goodModes[j])) {
					retVal = modes[i];
					break;
				}
			}
			
			if(!retVal.equals(null)) {
				break;
			}
		}
		
		return retVal;
	}
	
	public DisplayMode getCurrentDisplayMode() {
		return device.getDisplayMode();
	}
	
	public boolean displayModesMatch(DisplayMode mode1, DisplayMode mode2) {
		boolean retVal = true;
		
		if(mode1.getWidth() != mode2.getWidth() || mode1.getHeight() != mode2.getHeight()) {
			retVal = false;
		} else
		if(mode1.getBitDepth() != DisplayMode.BIT_DEPTH_MULTI &&
		   mode2.getBitDepth() != DisplayMode.BIT_DEPTH_MULTI &&
		   mode1.getBitDepth() != mode2.getBitDepth()) {
			retVal = false;
		} else
		if(mode1.getRefreshRate() != DisplayMode.REFRESH_RATE_UNKNOWN &&
		   mode2.getRefreshRate() != DisplayMode.REFRESH_RATE_UNKNOWN &&
		   mode1.getRefreshRate() != mode2.getRefreshRate()) {
			retVal = false;
		}
		
		return retVal;
	}
	
	public void setFullScreen(DisplayMode displayMode) {
		final JFrame frame = new JFrame();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setUndecorated(true);
		frame.setIgnoreRepaint(true);
		frame.setResizable(false);
		
		device.setFullScreenWindow(frame);
		
		if(displayMode != null && device.isDisplayChangeSupported()) {
			try {
				device.setDisplayMode(displayMode);
			} catch(IllegalArgumentException iae) {
				// Absorb exception
			}
			
			// For Mac OS X
			frame.setSize(displayMode.getWidth(), displayMode.getHeight());
		}
		
		// Avoid potential deadlock in 1.4.1_02
		try {
			EventQueue.invokeAndWait(new Runnable() {
				public void run() {
					frame.createBufferStrategy(2);
				}
			});
		} catch(InterruptedException ie) {
			// Absorb exception
		} catch(InvocationTargetException ite) {
			// Absorb exception
		}
	}
	
	public Graphics2D getGraphics() {
		Graphics2D retVal = null;
		Window window = device.getFullScreenWindow();
		
		if(window != null) {
			BufferStrategy strategy = window.getBufferStrategy();
			retVal = (Graphics2D)strategy.getDrawGraphics();
		}
		
		return retVal;
	}
	
	public void update() {
		Window window = device.getFullScreenWindow();
		
		if(window !=null) {
			BufferStrategy strategy = window.getBufferStrategy();
			
			if(!strategy.contentsLost()) {
				strategy.show();
			}
		}
		
		Toolkit.getDefaultToolkit().sync();
	}
	
	public JFrame getFullScreenWindow() {
		return (JFrame)device.getFullScreenWindow();
	}
	
	public int getWidth() {
		int retVal = 0;
		Window window = device.getFullScreenWindow();
		
		if(window != null) {
			retVal = window.getWidth();
		}
		
		return retVal;
	}

	public int getHeight() {
		int retVal = 0;
		Window window = device.getFullScreenWindow();
		
		if(window != null) {
			retVal = window.getHeight();
		}
		
		return retVal;
	}
	
	public void restoreScreen() {
		Window window = device.getFullScreenWindow();
		
		if(window != null) {
			window.dispose();
		}
		
		device.setFullScreenWindow(null);
	}
	
	public BufferedImage createCompatibleImage(int w, int h, int transparency) {
		BufferedImage retVal = null;
		Window window = device.getFullScreenWindow();
		
		if(window != null) {
			GraphicsConfiguration gc = window.getGraphicsConfiguration();
			retVal = gc.createCompatibleImage(w, h, transparency);
		}
		
		return retVal;
	}

}
